﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace VidoopSecure
{
    public class Captcha
    {

        private string _id;
        private int _length;
        private bool _orderMatters;
        private int _width;
        private int _height;
        private string _imageCodeColor;
        private string _image;
        private bool _attempted;
        private bool _authenticated;
        private string _xml;
        private List<string> _categories;
        private string _instructionText;

        /// <summary>
        /// Captcha Id
        /// </summary>
        public string Id 
        { 
            get { return _id; } 
            set { _id = value; } 
        }

        /// <summary>
        /// Number of categories that must be entered to solve the Captcha.
        /// </summary>
        public int Length 
        { 
            get { return _length; } 
            set { _length = value; } 
        }

        /// <summary>
        /// Whether the categories must be entered in order.
        /// </summary>
        public bool OrderMatters 
        { 
            get { return _orderMatters; } 
            set { _orderMatters = value; } 
        }

        /// <summary>
        /// Width of the Captcha in number of images.
        /// </summary>
        public int Width 
        { 
            get { return _width; } 
            set { _width = value; } 
        }

        /// <summary>
        /// Height of the Captcha in number of images.
        /// </summary>
        public int Height 
        { 
            get { return _height; } 
            set { _height = value; } 
        }

        /// <summary>
        /// Color of the image code.
        /// </summary>
        public string ImageCodeColor 
        { 
            get { return _imageCodeColor; } 
            set { _imageCodeColor = value; } 
        }

        /// <summary>
        /// Url of Captcha image to display to the user.
        /// </summary>
        public string Image 
        { 
            get { return _image; } 
            set { _image = value; } 
        }

        /// <summary>
        /// Has solution of this Captcha already been attempted.
        /// </summary>
        public bool Attempted 
        { 
            get { return _attempted; } 
            set { _attempted = value; } 
        }

        /// <summary>
        /// Was this Captcha successfully authenticated.
        /// </summary>
        public bool Authenticated 
        { 
            get { return _authenticated; } 
            set { _authenticated = value; } 
        }

        /// <summary>
        /// Raw XML string from which this Captcha object was created.
        /// </summary>
        public string Xml 
        { 
            get { return _xml; } 
            set { _xml = value; } 
        }

        /// <summary>
        /// The image categories which should be identified in the Captcha.
        /// </summary>
        public List<string> Categories 
        { 
            get { return _categories; } 
            set { _categories = value; } 
        }

        /// <summary>
        /// The text instructing the user how to identify the Captcha.
        /// </summary>
        public string InstructionText 
        { 
            get { return _instructionText; } 
            set { _instructionText = value; } 
        }


        /// <summary>
        /// Generate a Captcha instance from the provided XML.
        /// </summary>
        /// <remarks>
        /// <paramref name="xml"/> looks like this:
        /// <![CDATA[
        /// <captcha>                      
        ///     <id>6EEPEA97W2</id>        
        ///     <captcha_length>3</captcha_length>
        ///     <order_matters>False</order_matters>
        ///     <width>4</width>
        ///     <height>3</height>         
        ///     <image_code_color>Red</image_code_color>
        ///     <category_names>
        ///         <category_name>food</category_name>
        ///         <category_name>flowers</category_name>
        ///         <category_name>people</category_name>
        ///     </category_names>          
        ///     <text>Enter the letters for food, flowers and people, and click Submit.</text>
        ///     <imageURI>https://api.vidoop.com/vs/captchas/6EEPEA97W2/image</imageURI>
        ///     <attempted>false</attempted>    
        ///     <authenticated>false</authenticated>
        /// </captcha>
        ///]]>
        /// </remarks>
        /// <param name="xml">A <see cref="System.String" /> containing the
        /// xml representation of a Captcha.</param>
        /// <returns>An instance of a <see cref="VidoopSecure.Captcha" />.</returns>
        /// <seealso cref="VidoopSecure" />
        public static Captcha FromXml(string xml) 
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            return GenerateCaptchaFromXmlDocument(doc);
        }

        /// <summary>
        /// Generate a Captcha instance from the XML in <paramref="stream" />.
        /// </summary>
        /// <remarks>
        /// <paramref name="xml"/> looks like this:
        /// <![CDATA[
        /// <captcha>                      
        ///     <id>6EEPEA97W2</id>        
        ///     <captcha_length>3</captcha_length>
        ///     <order_matters>False</order_matters>
        ///     <width>4</width>
        ///     <height>3</height>         
        ///     <image_code_color>Red</image_code_color>
        ///     <category_names>
        ///         <category_name>food</category_name>
        ///         <category_name>flowers</category_name>
        ///         <category_name>people</category_name>
        ///     </category_names>          
        ///     <text>Enter the letters for food, flowers and people, and click Submit.</text>
        ///     <imageURI>https://api.vidoop.com/vs/captchas/6EEPEA97W2/image</imageURI>
        ///     <attempted>false</attempted>    
        ///     <authenticated>false</authenticated>
        /// </captcha>
        ///]]>
        /// </remarks>
        /// <param name="xml">A <see cref="System.String" /> containing the
        /// xml representation of a Captcha.</param>
        /// <returns>An instance of a <see cref="VidoopSecure.Captcha" />.</returns>
        /// <seealso cref="VidoopSecure" />
        public static Captcha FromXml(Stream stream) 
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(stream);
            return GenerateCaptchaFromXmlDocument(doc);
        }

        static private Captcha GenerateCaptchaFromXmlDocument(XmlDocument doc)
        {
            Captcha captcha = new Captcha();
            captcha.Xml = doc.OuterXml;
            captcha.Id = doc.GetElementsByTagName("id")[0].InnerText;
            captcha.Length = int.Parse(doc.GetElementsByTagName("captcha_length")[0].InnerText);
            captcha.OrderMatters = bool.Parse(doc.GetElementsByTagName("order_matters")[0].InnerText);
            captcha.Width = int.Parse(doc.GetElementsByTagName("width")[0].InnerText);
            captcha.Height = int.Parse(doc.GetElementsByTagName("height")[0].InnerText);
            captcha.ImageCodeColor = doc.GetElementsByTagName("image_code_color")[0].InnerText;
            captcha.Image = doc.GetElementsByTagName("imageURI")[0].InnerText;
            captcha.Attempted = bool.Parse(doc.GetElementsByTagName("attempted")[0].InnerText);
            captcha.Authenticated = bool.Parse(doc.GetElementsByTagName("authenticated")[0].InnerText);
            captcha.InstructionText = doc.GetElementsByTagName("text")[0].InnerText;


            XmlNodeList categoryNodes = doc.GetElementsByTagName("category_name");
            if (categoryNodes != null && categoryNodes.Count > 0)
            {
                captcha.Categories = new List<string>(categoryNodes.Count);
                foreach (XmlNode node in categoryNodes)
                    captcha.Categories.Add(node.InnerText);
            }
            return captcha;
        }
    }
}
